/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef FOUNDATION_ALIYUN_SRC_CLOUD_MODEL_REALTIME_AUDIO_H_
#define FOUNDATION_ALIYUN_SRC_CLOUD_MODEL_REALTIME_AUDIO_H_

#include <atomic>
#include <condition_variable>
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <nlohmann/json.hpp>
#include <queue>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>
#include "utils_noncopyable.h"

// libwebsockets前置声明
struct lws;
struct lws_context;
struct lws_protocols;

namespace El {

// 前向声明
namespace Media {
class StreamSource;
using StreamSourcePtr = std::shared_ptr<StreamSource>;
class MediaFrame;
using MediaFramePtr = std::shared_ptr<MediaFrame>;
} // namespace Media

namespace Cloud {
class RealtimeAudioTranscoder;

/**
 * @brief 实时音频会话状态
 */
enum class RealtimeSessionState {
    Disconnected, // 未连接
    Connecting,   // 连接中
    Connected,    // 已连接
    Speaking,     // 用户说话中
    Responding,   // AI响应中
    Error         // 错误状态
};

/**
 * @brief 音频数据格式
 */
struct AudioFormat {
    int32_t sampleRate{16000}; // 采样率(Hz)
    int32_t channels{1};       // 声道数
    int32_t bitsPerSample{16}; // 每个样本的位数
};

/**
 * @brief 实时音频事件回调
 */
struct RealtimeAudioCallbacks {
    // 连接状态变化回调
    std::function<void(RealtimeSessionState state)> onStateChanged;

    // 接收到AI音频数据回调
    std::function<void(const std::vector<uint8_t> &audioData)> onAudioReceived;

    // 接收到AI文本回复回调
    std::function<void(const std::string &text)> onTextReceived;

    // VAD检测到语音开始
    std::function<void()> onSpeechStart;

    // VAD检测到语音结束
    std::function<void()> onSpeechEnd;

    // 错误回调
    std::function<void(const std::string &error)> onError;
};

/**
 * @brief 阿里云实时多模态音频服务
 *
 * 基于WebSocket协议实现实时语音对话,支持:
 * - 流式音频输入/输出
 * - 内置VAD语音活动检测
 * - 多会话管理
 * - 多语言支持
 */
class CloudModelRealtimeAudio {
    DISALLOW_COPY_AND_MOVE(CloudModelRealtimeAudio);

public:
    static CloudModelRealtimeAudio &GetInstance();

    /**
     * @brief 启动实时音频服务
     * @return true=成功, false=失败
     */
    bool Start();

    /**
     * @brief 停止实时音频服务
     */
    void Stop();

    /**
     * @brief 启用自动音频流处理
     * @param channelId 音频通道ID (通常0表示麦克风)
     * @return true=成功, false=失败
     */
    bool EnableAutoAudioStream(int32_t channelId = 0);

    /**
     * @brief 禁用自动音频流处理
     */
    void DisableAutoAudioStream();

    /**
     * @brief 创建新的实时会话
     * @param callbacks 事件回调函数
     * @param audioFormat 音频格式
     * @return true=成功, false=失败
     */
    bool CreateSession(const RealtimeAudioCallbacks &callbacks, const AudioFormat &audioFormat = AudioFormat{});

    /**
     * @brief 删除会话
     * @return true=成功, false=失败
     */
    bool DeleteSession();

    /**
     * @brief 发送音频数据
     * @param audioData 音频数据(PCM格式)
     * @return true=成功, false=失败
     */
    bool SendAudioData(const std::vector<uint8_t> &audioData);

    /**
     * @brief 发送文本消息
     * @param text 文本内容
     * @return true=成功, false=失败
     */
    bool SendTextMessage(const std::string &text);

    /**
     * @brief 获取会话状态
     * @return 会话状态
     */
    RealtimeSessionState GetSessionState() const;

    /**
     * @brief 配置VAD参数
     * @param vadEnabled 是否启用VAD
     * @param vadThreshold VAD阈值(0.0-1.0)
     * @return true=成功, false=失败
     */
    bool ConfigureVAD(bool vadEnabled, float vadThreshold = 0.5f);

    /**
     * @brief 发送视频帧数据
     * @param videoData 视频帧数据(H264/H265编码)
     * @return true=成功, false=失败
     */
    bool SendVideoFrame(const std::vector<uint8_t> &videoData);

    /**
     * @brief 启用自动视频流处理
     * @param channelId 视频通道ID (通常0表示主码流)
     * @return true=成功, false=失败
     */
    bool EnableAutoVideoStream(int32_t channelId = 0);

    /**
     * @brief 禁用自动视频流处理
     */
    void DisableAutoVideoStream();

    /**
     * @brief 设置视频帧发送间隔
     * @param intervalMs 发送间隔(毫秒),默认1000ms
     * @return true=成功, false=失败
     */
    bool SetVideoFrameInterval(uint32_t intervalMs);

    // WebSocket回调处理 (需要public访问)
    static int WebSocketCallback(struct lws *wsi, int reason, void *user, void *in, size_t len);

private:
    CloudModelRealtimeAudio();
    ~CloudModelRealtimeAudio();

    /**
     * @brief 实时会话上下文
     */
    /**
     * @brief 实时会话上下文（单一会话）
     */
    struct SessionContext {
        RealtimeSessionState state{RealtimeSessionState::Disconnected};
        AudioFormat audioFormat;
        RealtimeAudioCallbacks callbacks;

        struct lws *wsi{nullptr};                   // WebSocket实例
        std::queue<std::vector<uint8_t>> sendQueue; // 发送队列
        std::mutex sendMutex;

        // 待发送的PCM缓冲
        std::vector<uint8_t> pendingPcmBuffer;
        std::mutex pendingPcmMutex;
        size_t inputChunkSizeBytes{0};

        bool vadEnabled{true};
        float vadThreshold{0.5f};

        // WebSocket接收缓冲区
        std::vector<uint8_t> recvBuffer;

        // 音频播放状态
        std::atomic<bool> isPlaying{false};

        // 事件ID生成器
        std::atomic<uint64_t> nextEventId{0};

        // 会话信息（从 session.created 事件获取）
        std::string sessionId;       // 服务端分配的会话ID
        std::string voice{"Cherry"}; // 语音类型
        int outputSampleRate{24000}; // 云端返回PCM采样率(Hz)

        // 保存 Authorization 头部字符串的生命周期
        std::string authHeader;

        // 追踪 response.content_part.* 事件信息
        std::unordered_map<std::string, std::string> contentPartTypes;
        std::unordered_map<std::string, std::string> contentPartTextBuffer;

        bool firstMessageLogged{false};

        // 视频帧相关
        uint64_t lastVideoFrameTime{0};   // 上次发送视频帧的时间戳(微秒)
        uint32_t videoFrameInterval{1000}; // 视频帧发送间隔(毫秒)
    };

    bool InitConfig();
    bool InitWebSocket();
    void CleanupWebSocket();

    // WebSocket工作线程
    void WebSocketThreadFunc();

    // WebSocket事件处理
    int HandleWebSocketEvent(SessionContext *session, struct lws *wsi, int reason, void *in, size_t len);

    // 消息处理
    void HandleReceivedMessage(SessionContext *session, const std::string &message);
    void HandleSessionCreatedEvent(SessionContext *session, const nlohmann::json &event);
    void HandleSessionUpdatedEvent(SessionContext *session, const nlohmann::json &event);
    void HandleResponseCreatedEvent(SessionContext *session, const nlohmann::json &event);
    void HandleResponseAudioDelta(SessionContext *session, const nlohmann::json &event);
    void HandleResponseOutputItemAdded(SessionContext *session, const nlohmann::json &event);
    void HandleResponseContentPartAdded(SessionContext *session, const nlohmann::json &event);
    void HandleResponseContentPartDelta(SessionContext *session, const nlohmann::json &event);
    void HandleResponseContentPartDone(SessionContext *session, const nlohmann::json &event);
    void HandleResponseAudioTranscriptDelta(SessionContext *session, const nlohmann::json &event);
    void HandleResponseCompleted(SessionContext *session, const nlohmann::json &event);
    void HandleResponseAudioDone(SessionContext *session, const nlohmann::json &event);
    void HandleResponseTextDelta(SessionContext *session, const nlohmann::json &event);
    void HandleResponseTextDone(SessionContext *session, const nlohmann::json &event);
    void HandleInputAudioBufferSpeechStarted(SessionContext *session, const nlohmann::json &event);
    void HandleInputAudioBufferSpeechStopped(SessionContext *session, const nlohmann::json &event);
    void HandleErrorEvent(SessionContext *session, const nlohmann::json &event);
    void ConfigurePlaybackSampleRate(SessionContext *session, const std::string &pcmFormat);
    void HandleInputAudioBufferCommitted(SessionContext *session, const nlohmann::json &event);
    void HandleConversationItemCreated(SessionContext *session, const nlohmann::json &event);
    void HandleConversationInputAudioTranscriptionCompleted(SessionContext *session, const nlohmann::json &event);
    void HandleResponseAudioTranscriptDone(SessionContext *session, const nlohmann::json &event);
    void HandleResponseOutputItemDone(SessionContext *session, const nlohmann::json &event);
    void HandleResponseDone(SessionContext *session, const nlohmann::json &event);
    bool FlushPendingInputAudio(SessionContext *session, bool flushPartial);
    size_t CalculateInputChunkSizeBytes(const AudioFormat &format) const;
    void ScheduleWritable(SessionContext *session);

    // 连接管理
    bool Connect();
    void Disconnect();

    // 会话状态管理
    void UpdateSessionState(SessionContext *session, RealtimeSessionState newState);
    SessionContext *GetSession();

    // 音频流处理
    void ProcessAudioFrame(const El::Media::MediaFramePtr &frame);
    void HandleCloudAudioForPlayback(SessionContext *session, const std::vector<uint8_t> &pcmData);

    // 视频流处理
    void ProcessVideoFrame(const El::Media::MediaFramePtr &frame);

    // 发送队列大小限制
    static constexpr size_t kMaxSendQueueSize = 100;
    static constexpr uint32_t kInputChunkDurationMs = 80;

private:
    std::string api_key_;
    std::string ws_url_;
    std::string model_name_;

    // 默认会话参数（来自配置）
    bool default_vad_enabled_{true};
    float default_vad_threshold_{0.5f};
    AudioFormat default_audio_format_{}; // 16000/1/16 默认

    // WebSocket上下文
    struct lws_context *ws_context_{nullptr};
    std::unique_ptr<std::thread> ws_thread_;
    std::atomic<bool> running_{false};

    // 单一会话
    SessionContext session_;
    std::mutex session_mutex_;

    // 音频转码器
    std::unique_ptr<RealtimeAudioTranscoder> transcoder_;

    // 音频流源
    El::Media::StreamSourcePtr audioStream_;
    int32_t streamHandle_{-1};

    // 视频流源
    El::Media::StreamSourcePtr videoStream_;
    int32_t videoStreamHandle_{-1};
};

} // namespace Cloud
} // namespace El

#endif // FOUNDATION_ALIYUN_SRC_CLOUD_MODEL_REALTIME_AUDIO_H_
